﻿Option Infer On

Imports System.IO
Imports System.Text.RegularExpressions

' TODO Namespace Helpers

Public Class Utility

    Private Shared _data As ArtikelsDataSet
    Private Shared _samengesteldeArtikelsDs As SamengesteldeArtikelsDataSet
    Private Shared _deelArtikelIds As List(Of Integer)
    Private Shared _artikelSamenstelling As ArtikelSamenstelling

#Region "Public property's"

    Public Shared ReadOnly Property Data() As ArtikelsDataSet
        Get
            If (_data Is Nothing) Then
                InitializeData()
            End If
            Return _data
        End Get
    End Property

    Public Shared ReadOnly Property ArtikelSamenstelling() As ArtikelSamenstelling
        Get
            If (_artikelSamenstelling Is Nothing) Then
                _artikelSamenstelling = New ArtikelSamenstelling()
            End If
            Return _artikelSamenstelling
        End Get
    End Property

    ''' <summary>
    ''' Samengestelde artikels
    ''' </summary>
    ''' <remarks>Let op: wordt nog niet gerefresht bij wijzigingen! (alleen bij wijzigingen door dubbele barcodes</remarks>
    Public Shared ReadOnly Property SamengesteldeArtikels() As SamengesteldeArtikelsDataSet.SamengesteldeArtikelsDataTable
        Get
            If (_samengesteldeArtikelsDs Is Nothing) Then
                _samengesteldeArtikelsDs = SamengesteldeArtikelsDal.PrepareSamengesteldeArtikelsDataSet()
            End If
            Return _samengesteldeArtikelsDs.SamengesteldeArtikels
        End Get
    End Property

    Public Shared ReadOnly Property DeelartikelIds() As List(Of Integer)
        Get
            Return (From sa In SamengesteldeArtikels _
                    Select sa.DeelArtikelId) _
                    .Distinct() _
                    .ToList()
        End Get
    End Property

#End Region

#Region "Public methods"

    Public Shared Function ToDecimal(ByVal input As String) As Decimal
        input = input.Replace(".", ",")
        Dim resultaat As Decimal
        If (Decimal.TryParse(input, resultaat)) Then Return resultaat
        Return 0D
    End Function

    Public Shared Function IsOefenVersie() As Boolean
#If OEFEN Then
        ' Indien gebuild onder de "Oefen"-configuratie, dan is OEFEN gedefinieerd en is het een oefenversie
        Return True
#Else
        Return Environment.GetCommandLineArgs.Contains("/oefen")
#End If
    End Function

    Public Shared ReadOnly Property GetOefenVersieColor() As Color
        Get
            Return Color.FromArgb(255, 235, 220)
        End Get
    End Property

    Public Shared Sub ResetData()
        _data = Nothing
    End Sub

    Public Shared Sub ResetSamengesteldeArtikels()
        _samengesteldeArtikelsDs = Nothing
        _artikelSamenstelling = Nothing
    End Sub

    Public Shared Sub InitializeData()
        _data = Dal.PrepareArtikelsDataset()
    End Sub

    ''' <summary>
    ''' Haal de Artikeltabel opnieuw op tijdens een verkoop.
    ''' Dit kan nuttig zijn als je via een andere weg de databank aangepast hebt 
    ''' (rechtstreeks in Access of via een andere account op de pc)
    ''' Zonder deze methode blijf je altijd op de origineel ingeladen data werken 
    ''' zolang de verkoop niet afgesloten wordt.
    ''' </summary>
    Public Shared Sub VerversArtikelsFromDatabase()
        Dal.VerversArtikelsFromDatabase(_data)
    End Sub

    Public Shared Function HasChanges(ByVal dt As DataTable) As Boolean
        Return dt.GetChanges IsNot Nothing
    End Function

    ''' <summary>
    ''' Haal een grid een bepaalde datarow op, gecast naar het juiste type
    ''' </summary>
    ''' <typeparam name="T">Type van de datarow. Dit moet overerven van het type DataRow</typeparam>
    ''' <param name="grid">Grid</param>
    ''' <param name="rowIndex">Index van de rij binnen de grid</param>
    ''' <returns>De datarow van het juiste type. Als er geen datarow is (bijv. bij de lege rij onderaan), returns Nothing</returns>
    ''' <remarks>Voorbeeld:
    ''' Dim verkoopsDetailsRow As ArtikelsDataSet.VerkoopsDetailsRow = Utility.GetGridDataRow(Of ArtikelsDataSet.VerkoopsDetailsRow)(Grid1, rowIndex)</remarks>
    Public Shared Function GetGridDataRow(Of T As DataRow)(ByVal grid As DataGridView, ByVal rowIndex As Integer) As T
        Dim gridRow As DataGridViewRow = grid.Rows(rowIndex)
        Dim datarow As DataRowView = DirectCast(gridRow.DataBoundItem, DataRowView)
        If (datarow Is Nothing) Then Return Nothing ' bijvoorbeeld bij lege rij onderaan
        Return DirectCast(datarow.Row, T)
    End Function

    Public Shared Function HasDataChanged(ByVal e As BindingCompleteEventArgs, ByVal datamember As String) As Boolean
        If e.BindingCompleteContext = BindingCompleteContext.DataSourceUpdate Then
            If e.BindingCompleteState = BindingCompleteState.Success And _
                    Not e.Binding.Control.BindingContext.IsReadOnly Then

                'Make sure the data source value is refreshed (fixes problem mousing off control)
                e.Binding.ReadValue()
                'if not focused then not a user edit.
                If Not e.Binding.Control.Focused Then Exit Function ' werkt alleen als binding op OnPropertyChanged staat, niet op OnValidation

                'check for the lookup type of combobox that changes position instead of value
                Dim cb As ComboBox = TryCast(e.Binding.Control, ComboBox)
                If (cb IsNot Nothing) Then
                    'if the combo box has the same data member table as the binding source, ignore it
                    If cb.DataSource IsNot Nothing Then
                        If DirectCast(DirectCast(e.Binding.Control, ComboBox).DataSource,  _
                                BindingSource).DataMember = datamember Then Return False
                    End If
                End If
                Return True 'set the dirty flag because data was changed
            End If
        End If
        Return False
    End Function

    ''' <summary>
    ''' Leveringsbonnen kunnen soms geannuleerd worden.
    ''' Er wordt dan voor elk detail een tegengesteld detail toegevoegd.
    ''' Deze functie test of dit gebeurd is.
    ''' </summary>
    ''' <param name="verkoop"></param>
    Public Shared Function IsVerkoopGeannuleerd(ByVal verkoop As ArtikelsDataSet.VerkopenRow) As Boolean
        Dim verkoopsdetails As IList(Of ArtikelsDataSet.VerkoopsDetailsRow) = verkoop.GetVerkoopsDetailsRows().ToList()
        While (verkoopsdetails.Any())
            Dim detail1 As ArtikelsDataSet.VerkoopsDetailsRow = verkoopsdetails.First()
            Dim foundMatch As Boolean = False
            For Each detail2 As ArtikelsDataSet.VerkoopsDetailsRow In verkoopsdetails
                If (detail2.Id <> detail1.Id AndAlso detail2.IdArtikel = detail1.IdArtikel AndAlso detail2.Aantal = -detail1.Aantal) Then
                    verkoopsdetails.Remove(detail1)
                    verkoopsdetails.Remove(detail2)
                    foundMatch = True
                    Exit For
                End If
            Next
            If (Not foundMatch) Then Return False ' geen tegengesteld verkoopsdetail gevonden
        End While
        Return True ' voor alles een match gevonden
    End Function

    Public Shared Function CanOpenOtherFormCheck() As Boolean
        If (Utility.Data.HasChanges()) Then
            Dim changedTables As List(Of String) = Utility.Data.GetChangedTables()
            Dim strChangedTables As String = String.Join(", ", changedTables.ToArray())
            log.WriteInfo(String.Format("Tabellen ({0}) hebben nog wijzigingen waardoor een ander scherm niet kon geopend worden.", strChangedTables))
            MsgBox.ShowWarning("Omdat er nog niet bewaarde wijzigingen zijn in een ander scherm, mag je dit scherm niet openen. " & _
                    "Zorg ervoor dat eerst alles bewaard is in het andere scherm dat open is, en probeer dan opnieuw.")
            Return False
        Else
            Return True
        End If
    End Function

    Public Shared Sub GenereerRapport(ByVal xml As String, ByVal naamSjabloon As String)
        Using dataXmlStream As New MemoryStream()
            Using sw As New StreamWriter(dataXmlStream)
                sw.Write(xml)
                sw.Flush()
                dataXmlStream.Seek(0, SeekOrigin.Begin)
                Dim sjabloonLocatie As String = Path.Combine(Path.Combine( _
                        Path.GetDirectoryName(Application.ExecutablePath), "Sjablonen"), naamSjabloon)
                Dim builder As New fleXdoc.Api.DocBuilder(sjabloonLocatie)
                Dim tempFilename As String = Path.GetTempFileName()
                Dim outputFilename As String = tempFilename.Replace(Path.GetExtension(tempFilename), ".docx") ' TODO: later opruimen
                builder.Build(dataXmlStream, Nothing, Nothing, outputFilename, Globalization.CultureInfo.CurrentCulture, False)
                Process.Start(outputFilename)
            End Using
        End Using
    End Sub

    Public Shared Function FirstDayOfMonth(ByVal datum As Date) As Date
        Return New Date(datum.Year, datum.Month, 1)
    End Function

    Public Shared Function DesignMode() As Boolean
        Return System.Diagnostics.Process.GetCurrentProcess().ProcessName = "devenv"
    End Function

    Public Shared Function CheckValidZoekterm(ByVal invoer As String) As Boolean
        ' een of meerdere woorden gescheiden door een spatie
        Return Regex.IsMatch(invoer, "^[A-Za-z]+( [A-Za-z]+)*$")
    End Function

#End Region

End Class

'End Namespace
